/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.cef.generator.entityGenerator.base;


import com.inspur.edp.caf.generator.BaseGenerator;
import com.inspur.edp.caf.generator.composite.CompositeGenerator;
import com.inspur.edp.caf.generator.composite.CompositeGeneratorContext;
import com.inspur.edp.cef.designtime.api.IGspCommonDataType;
import com.inspur.edp.cef.designtime.api.IGspCommonField;
import com.inspur.edp.cef.designtime.api.element.GspAssociation;
import com.inspur.edp.cef.designtime.api.element.GspElementObjectType;
import com.inspur.edp.cef.generator.entityGenerator.BaseEntityGeneratorContext;
import com.inspur.edp.cef.generator.entityGenerator.base.dataTypeData.DataTypeDataGenerator;
import com.inspur.edp.cef.generator.entityGenerator.base.elements.ElementAssoGenerator;
import com.inspur.edp.cef.generator.entityGenerator.base.elements.ElementEnumGenerator;
import com.inspur.edp.cef.generator.entityGenerator.base.nodeConst.DataTypeConstGenerator;

import java.util.ArrayList;

import static com.inspur.edp.cef.designtime.api.variable.VariableSourceType.Context;

public abstract class DataTypeGenerator extends CompositeGenerator {
    protected IGspCommonDataType dataType;
    protected BaseEntityGeneratorContext entityGenContext;

    protected DataTypeGenerator(
            IGspCommonDataType dataType, BaseEntityGeneratorContext entityGenContext) {
        this.dataType = dataType;
        this.entityGenContext = entityGenContext;
    }

    protected DataTypeGeneratorContext getContext() {
        return (DataTypeGeneratorContext) super.getContext();
    }

    @Override
    protected final CompositeGeneratorContext createCompositeContext() {
        DataTypeGeneratorContext context = createDataTypeGenContext();
        entityGenContext.getDataTypeGenContexts().put(dataType.getCode(), context);
        return context;
    }

    protected abstract DataTypeGeneratorContext createDataTypeGenContext();

    // region CreateCompositeItemGenerators
    @Override
    protected ArrayList<BaseGenerator> createCompositeItemGenerators() {
        java.util.ArrayList<BaseGenerator> list = new java.util.ArrayList<BaseGenerator>();
        list.add(createConstGenerator());
        list.addAll(getNodeElementTypeGenerators());
        list.add(getDataGenerator());
        // list.add(new DataTypeSerializerGenerator(dataType, Context));
        java.util.ArrayList<BaseGenerator> extend = getDataTypeExtendGenerators();
        if (extend != null) {
            list.addAll(extend);
        }
        return list;
    }

    protected java.util.ArrayList<BaseGenerator> getDataTypeExtendGenerators() {
        return null;
    }

    protected DataTypeConstGenerator createConstGenerator() {
        return new DataTypeConstGenerator(dataType, getContext());
    }

    private ArrayList<BaseGenerator> getNodeElementTypeGenerators() {
        ArrayList<BaseGenerator> list = new ArrayList<BaseGenerator>();
        for (IGspCommonField item : dataType.getContainElements()) {
            if (item.getIsRefElement() || item.getIsRef()) {
                continue;
            }
            if (item.getObjectType() == GspElementObjectType.Association && !item.getIsUdt()) {
                list.addAll(getElementAssocationGenerators(item));
            } else if (item.getObjectType() == GspElementObjectType.Enum) {
                list.add(getElementEnumClassGenerator(item));
            }
        }
        return list;
    }

    private java.util.ArrayList<BaseGenerator> getElementAssocationGenerators(IGspCommonField field) {
        java.util.ArrayList<BaseGenerator> list = new java.util.ArrayList<BaseGenerator>();
        if (field.getChildAssociations() == null || field.getChildAssociations().size() == 0) {
            return list;
        }
        for (GspAssociation item : field.getChildAssociations()) {
            list.add(getFieldAssClassGenerator(field, item));
        }
        return list;
    }

    protected BaseGenerator getFieldAssClassGenerator(
            IGspCommonField field, GspAssociation association) {
        return new ElementAssoGenerator(field, association, getContext());
    }

    protected ElementEnumGenerator getElementEnumClassGenerator(IGspCommonField field) {
        return new ElementEnumGenerator(field, getContext());
    }

    protected abstract DataTypeDataGenerator getDataGenerator();
    // endregion

}
